<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
	<head>
		<title>Startup Template</title>
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
		<meta name="viewport" content="width=device-width initial-scale=1">
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<meta http-equiv="Content-Language" content="en-gb">

<link href="../docs-assets/Contents.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Progress.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Navigation.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Fonts.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
		
	</head>
	<body class="commentary-font">
		<nav role="navigation">
		<h1><a href="../index.html">
<img src="../docs-assets/Inform.png" height=72">
</a></h1>
<ul><li><a href="../index.html">home</a></li>
</ul><h2>Compiler</h2><ul>
<li><a href="../structure.html">structure</a></li>
<li><a href="../inbuildn.html">inbuild</a></li>
<li><a href="../inform7n.html">inform7</a></li>
<li><a href="../intern.html">inter</a></li>
<li><a href="../services.html">services</a></li>
<li><a href="../secrets.html">secrets</a></li>
</ul><h2>Other Tools</h2><ul>
<li><a href="../inblorbn.html">inblorb</a></li>
<li><a href="../indocn.html">indoc</a></li>
<li><a href="../inform6.html">inform6</a></li>
<li><a href="../inpolicyn.html">inpolicy</a></li>
</ul><h2>Resources</h2><ul>
<li><a href="../extensions.html">extensions</a></li>
<li><a href="../kits.html">kits</a></li>
</ul><h2>Repository</h2><ul>
<li><a href="https://github.com/ganelson/inform"><img src="../docs-assets/github.png" height=18> github</a></li>
</ul><h2>Related Projects</h2><ul>
<li><a href="../../../inweb/index.html">inweb</a></li>
<li><a href="../../../intest/index.html">intest</a></li>

</ul>
		</nav>
		<main role="main">
		<!-- Weave of 'Startup Template' generated by Inweb -->
<div class="breadcrumbs">
    <ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../extensions.html">Kits</a></li><li><a href="index.html">BasicInformKit</a></li><li><b>Startup Template</b></li></ul></div>
<p class="purpose">How the program starts up, in a Basic Inform project.</p>

<ul class="toc"><li><a href="S-str.html#SP1">&#167;1. Summary</a></li><li><a href="S-str.html#SP2">&#167;2. The startup sequence</a></li><li><a href="S-str.html#SP3">&#167;3. Initialise Memory Rule</a></li><li><a href="S-str.html#SP4">&#167;4. Seed Random Number Generator Rule</a></li></ul><hr class="tocbar">

<p class="commentary firstcommentary"><a id="SP1" class="paragraph-anchor"></a><b>&#167;1. Summary. </b>These rules perform the essential tasks required for setting up the virtual
machine. This includes checking that we are running in a compatible interpreter,
and setting up various built in Glk objects (when running in a Glk interpreter).
</p>

<p class="commentary">These rules here are the ones which get the basic machinery working
to the point where it is safe to run arbitrary I7 source text. They necessarily
do very low-level things, and it is not guaranteed that I7 phrases will behave
to specification if executed before these early rules have finished. So it
is hazardous to obstruct or alter them.
</p>

<p class="commentary">Arrangements are a little different here on the Z-machine, because some
data is retained in the case of a restart.
</p>

<p class="commentary">(Many thanks are due to Eliuk Blau, who found several tricky timing errors
here and elsewhere in the Glulx-specific code. Frankly, I feel like hanging
a sign on the following routines which reads "Congratulations on bringing
light to the Dark Room.")
</p>

<p class="commentary firstcommentary"><a id="SP2" class="paragraph-anchor"></a><b>&#167;2. The startup sequence. </b>As of IE-0022 we have a simplified startup sequence. <span class="extract"><span class="extract-syntax">Main</span></span> calls the <span class="extract"><span class="extract-syntax">Startup</span></span>
function, which does two things: run an Architecture16Kit/Architecture32Kit function
<span class="extract"><span class="extract-syntax">VM_Check_Functionality</span></span> which checks the VM meets the minimum requirements for Inform
(in Glulx it would test a few Glulx/Glk gestalts; in Z-Code it would probably do
nothing.) Then it runs the Startup Rules. And that's it - everything else in the
startup sequence is now in Inform-accessible rules.
</p>

<p class="commentary">Because the functions below are replaced by <span class="extract"><span class="extract-syntax">WorldModelKit</span></span> alternatives
if that kit is present, the following applies only to Basic Inform programs
where <span class="extract"><span class="extract-syntax">WorldModelKit</span></span> is not involved.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">Main</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">self</span><span class="plain-syntax"> = </span><span class="identifier-syntax">COL_HSIZE</span><span class="plain-syntax">; </span><span class="comment-syntax">To ensure this definition is not optimised out</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">Startup</span><span class="plain-syntax">();</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">Submain</span><span class="plain-syntax">();</span>
<span class="plain-syntax">];</span>

<span class="plain-syntax">[ </span><span class="identifier-syntax">Startup</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">VM_Check_Functionality</span><span class="plain-syntax">();</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">say__pc</span><span class="plain-syntax"> = </span><span class="identifier-syntax">say__pc</span><span class="plain-syntax"> | </span><span class="identifier-syntax">PARA_NORULEBOOKBREAKS</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">FollowRulebook</span><span class="plain-syntax">(</span><span class="identifier-syntax">STARTUP_RB</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">say__pc</span><span class="plain-syntax"> &amp; </span><span class="identifier-syntax">PARA_NORULEBOOKBREAKS</span><span class="plain-syntax">) </span><span class="identifier-syntax">say__pc</span><span class="plain-syntax"> = </span><span class="identifier-syntax">say__pc</span><span class="plain-syntax"> - </span><span class="identifier-syntax">PARA_NORULEBOOKBREAKS</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">rfalse</span><span class="plain-syntax">;</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP3" class="paragraph-anchor"></a><b>&#167;3. Initialise Memory Rule. </b>This rule amalgamates some minimal initialisations which all need to happen
before we can risk using some of the more exotic I7 kinds:
</p>

<ul class="items"><li>(a) The language definition might call for initialisation, although the
default language of play (English) does not.
</li><li>(b) We start the machinery needed to check that property accesses are
valid during play.
</li><li>(c) We initialise the memory allocation heap, and expand the literal
constants, as hinted above: these are called "block constants" since
they occupy blocks of memory.
</li><li>(d) Some architecture-specific dictionary and parse buffer related globals
are initialised.
</li></ul>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">INITIALISE_MEMORY_R</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LanguageInitialise</span><span class="plain-syntax">();</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">HeapInitialise</span><span class="plain-syntax">(); </span><span class="comment-syntax">Create a completely unused memory allocation heap</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">StackFramingInitialise</span><span class="plain-syntax">(); </span><span class="comment-syntax">Create an empty stack</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">CreateDynamicRelations</span><span class="plain-syntax">(); </span><span class="comment-syntax">Create relation structures on the heap</span>

<span class="plain-syntax">    #</span><span class="identifier-syntax">Ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">TARGET_GLULX</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="comment-syntax">Empty the parse buffer (see bug 0001451)</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">buffer3</span><span class="plain-syntax">--&gt;0 = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">Ifnot</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">standard_interpreter</span><span class="plain-syntax"> = </span><span class="identifier-syntax">HDR_TERPSTANDARD</span><span class="plain-syntax">--&gt;0;</span>

<span class="plain-syntax">        </span><span class="identifier-syntax">dict_start</span><span class="plain-syntax"> = </span><span class="identifier-syntax">HDR_DICTIONARY</span><span class="plain-syntax">--&gt;0;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">dict_entry_size</span><span class="plain-syntax"> = </span><span class="identifier-syntax">dict_start</span><span class="plain-syntax">-&gt;(</span><span class="identifier-syntax">dict_start</span><span class="plain-syntax">-&gt;0 + </span><span class="constant-syntax">1</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">dict_start</span><span class="plain-syntax"> = </span><span class="identifier-syntax">dict_start</span><span class="plain-syntax"> + </span><span class="identifier-syntax">dict_start</span><span class="plain-syntax">-&gt;0 + </span><span class="constant-syntax">4</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">dict_end</span><span class="plain-syntax"> = </span><span class="identifier-syntax">dict_start</span><span class="plain-syntax"> + ((</span><span class="identifier-syntax">dict_start</span><span class="plain-syntax"> - </span><span class="constant-syntax">2</span><span class="plain-syntax">)--&gt;0) * </span><span class="identifier-syntax">dict_entry_size</span><span class="plain-syntax">;</span>

<span class="plain-syntax">        </span><span class="identifier-syntax">buffer</span><span class="plain-syntax">-&gt;0  = </span><span class="identifier-syntax">INPUT_BUFFER_LEN</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">buffer2</span><span class="plain-syntax">-&gt;0 = </span><span class="identifier-syntax">INPUT_BUFFER_LEN</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">buffer3</span><span class="plain-syntax">-&gt;0 = </span><span class="identifier-syntax">INPUT_BUFFER_LEN</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">parse</span><span class="plain-syntax">-&gt;0   = </span><span class="constant-syntax">15</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">parse2</span><span class="plain-syntax">-&gt;0  = </span><span class="constant-syntax">15</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">Endif</span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">rfalse</span><span class="plain-syntax">;</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP4" class="paragraph-anchor"></a><b>&#167;4. Seed Random Number Generator Rule. </b>Unless a seed is provided by Inform, and it won't be for released story files,
the VM's interpreter is supposed to start up with a good seed in its random
number generator: something usually derived from, say, the milliseconds part
of the current time of day, which is unlikely to repeat or show any pattern
in real-world use. However, early Z-machine interpreters often did this quite
badly, starting with poor seed values which meant that the first few random
numbers always had something in common (being fairly small in their range,
for instance).
</p>

<p class="commentary">More recently, many Glulx interpreters also had
[a major flaw](<a href="https://intfiction.org/t/lack-of-randomness-sometimes-when-compiling-for-glulx/64533" class="external">https://intfiction.org/t/lack-of-randomness-sometimes-when-compiling-for-glulx/64533</a>)
in which repeatedly calling `random(N)` when `N` was a power of 2 resulted in
there only being `N` distinct sequences. Even worse, the first number of each
sequence might be the same! This would mean that, for example, if a mystery
game randomly selected the murderer from five candidates the results might
appear random, but if there were only four candidates then the same one would
be chosen *every* playthrough.
</p>

<p class="commentary">To attempt to partially mitigate these problems, we extract and throw away a
number of random numbers to get the generator going, shaking out more obvious
early patterns. Because of the particular nature of the flaw in those Glulx
interpreters, we do this a random number of times.
</p>

<p class="commentary">Most interpreters have been updated recently to improve their random algorithms,
but if we're running in something really old, there's only so much we can do
to account for it. Story files which rely on quality randomness may need to
use an extension to use a new algorithm instead of the one provided by the
interpreter. Extensions are also needed if you want a random algorithm that is
consistent across interpreters (for example, to be able to share a seed that
generates the same dungeon in an procedurally-generated RPG.)
</p>

<p class="commentary">"Anyone who considers arithmetical methods of producing random digits is,
of course, in a state of sin" (von Neumann).
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">SEED_RANDOM_NUMBER_GENERATOR_R</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax"> </span><span class="identifier-syntax">count</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">BasicInformKit</span><span class="plain-syntax">`</span><span class="identifier-syntax">FIX_RNG_CFGF</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        #</span><span class="identifier-syntax">Ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">TARGET_GLULX</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            @</span><span class="reserved-syntax">random</span><span class="plain-syntax"> </span><span class="constant-syntax">10000</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">i</span><span class="plain-syntax"> = -</span><span class="identifier-syntax">i</span><span class="plain-syntax">-2000;</span>
<span class="plain-syntax">            @</span><span class="identifier-syntax">setrandom</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        #</span><span class="identifier-syntax">Ifnot</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            @</span><span class="reserved-syntax">random</span><span class="plain-syntax"> </span><span class="constant-syntax">10000</span><span class="plain-syntax"> -&gt; </span><span class="identifier-syntax">i</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">i</span><span class="plain-syntax"> = -</span><span class="identifier-syntax">i</span><span class="plain-syntax">-2000;</span>
<span class="plain-syntax">            @</span><span class="reserved-syntax">random</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax"> -&gt; </span><span class="identifier-syntax">i</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        #</span><span class="identifier-syntax">Endif</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">RNG_SEED_AT_START_OF_PLAY</span><span class="plain-syntax">) </span><span class="identifier-syntax">VM_Seed_RNG</span><span class="plain-syntax">(</span><span class="identifier-syntax">RNG_SEED_AT_START_OF_PLAY</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">count</span><span class="plain-syntax"> = </span><span class="reserved-syntax">random</span><span class="plain-syntax">(97);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">i</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">: </span><span class="identifier-syntax">i</span><span class="plain-syntax"> &lt;= </span><span class="identifier-syntax">count</span><span class="plain-syntax">: </span><span class="identifier-syntax">i</span><span class="plain-syntax">++) </span><span class="reserved-syntax">random</span><span class="plain-syntax">(</span><span class="identifier-syntax">i</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">rfalse</span><span class="plain-syntax">;</span>
<span class="plain-syntax">];</span>
</pre>
<nav role="progress"><div class="progresscontainer">
    <ul class="progressbar"><li class="progressprev"><a href="S-dfn.html">&#10094;</a></li><li class="progresssection"><a href="S-dfn.html">dfn</a></li><li class="progresscurrent">str</li><li class="progresssection"><a href="S-utl.html">utl</a></li><li class="progresssection"><a href="S-prg.html">prg</a></li><li class="progresssection"><a href="S-mth.html">mth</a></li><li class="progresssection"><a href="S-srt.html">srt</a></li><li class="progresssection"><a href="S-tbl.html">tbl</a></li><li class="progresssection"><a href="S-mst.html">mst</a></li><li class="progresssection"><a href="S-rlb.html">rlb</a></li><li class="progresssection"><a href="S-act.html">act</a></li><li class="progresssection"><a href="S-prn.html">prn</a></li><li class="progresssection"><a href="S-flx.html">flx</a></li><li class="progresssection"><a href="S-blc.html">blc</a></li><li class="progresssection"><a href="S-knd.html">knd</a></li><li class="progresssection"><a href="S-txt.html">txt</a></li><li class="progresssection"><a href="S-chr.html">chr</a></li><li class="progresssection"><a href="S-rgx.html">rgx</a></li><li class="progresssection"><a href="S-lst.html">lst</a></li><li class="progresssection"><a href="S-cmb.html">cmb</a></li><li class="progresssection"><a href="S-rlt.html">rlt</a></li><li class="progresssection"><a href="S-rlt2.html">rlt2</a></li><li class="progresssection"><a href="S-prp.html">prp</a></li><li class="progresssection"><a href="S-rtp.html">rtp</a></li><li class="progressnext"><a href="S-utl.html">&#10095;</a></li></ul></div>
</nav><!-- End of weave -->

		</main>
	</body>
</html>

